package com.init.common.utils;
/**
 *
 **/

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.init.common.constant.Constants;
import com.init.common.exception.CustomException;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @Author weiwei
 * @Date 2021-10-12 15:03
 * @description
 **/
@Slf4j
public class TokenUtils {

    /**
     * 生成token
     * @param k_v 构建数据 索引偶数是key 奇数是value
     * @date 2020-07-21
     */
    public static String generateToken(String... k_v) {
        return generateToken(null,k_v);
    }
    /**
     * 生成token
     * @param k_v 构建数据 索引偶数是key 奇数是value
     * @date 2020-07-21
     */
    public static String generateToken(Long expireTime,String... k_v) {
        return commonGenerateToken(expireTime,"token",k_v);
    }

    /**
     *
     * @param k_v k_v 构建数据 索引偶数是key 奇数是value
     * @return
     */
    public static String generateRefreshToken(String... k_v){
        return generateRefreshToken(null,k_v);
    }
    /**
     *
     * @param k_v k_v 构建数据 索引偶数是key 奇数是value
     * @return
     */
    public static String generateRefreshToken(Long expireTime,String... k_v){
        return commonGenerateToken(expireTime,"refresh",k_v);
    }

    /**
     *
     * @param k_v 构建数据 索引偶数是key 奇数是value
     * @param type "token"构建正常token "refresh"构建正常刷新token
     * @return
     */
    public static String commonGenerateToken(Long expireTime,String type,String... k_v) {
        String token = null;
        try {
            if(expireTime == null){
                if(StringUtils.equals(type,"token")){
                    expireTime = Constants.EXPIRE_TIME;
                }
                if(StringUtils.equals(type,"refresh")){
                    expireTime = Constants.REFRESH_EXPIRE_TIME;
                }
            }
            Date expireAt = new Date(System.currentTimeMillis() + expireTime);
            JWTCreator.Builder builder = JWT.create()
                    //发行人
                    .withIssuer(Constants.PUBLISHER)
                    //过期时间
                    .withExpiresAt(expireAt);
            for (int i = 0; i < k_v.length; i++) {
                if(i%2 == 1){
                    builder.withClaim(k_v[i-1],k_v[i]);
                }
            }
            token = builder.sign(Algorithm.HMAC256(Constants.TOKEN_SECRET));

        } catch (Exception e) {
            throw new CustomException("jwt generate abnormal", new Throwable());
        }
        return token;
    }


    /**
     * token校验是否失效或正确
     * @param token
     * @return
     */
    public static boolean verifyToken(String token) {
        try {
            //创建token验证器
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(Constants.TOKEN_SECRET)).withIssuer(Constants.PUBLISHER).build();
            jwtVerifier.verify(token);
            return true;
        } catch (Exception e) {
            log.info("token解析失效：{}",e);
            return false;
        }
    }

    /**
     * token解析
     * @param token
     * @return
     */
    public static DecodedJWT parseToken(String token) {
        try {
            //创建token验证器
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(Constants.TOKEN_SECRET)).withIssuer(Constants.PUBLISHER).build();
            return jwtVerifier.verify(token);
        } catch (Exception e) {
            throw new CustomException("token error, parse failed");
        }
    }

    /**
     * 根据token获取企业人员id
     * @param request
     * @return
     */
    public static Long getUserId(HttpServletRequest request){
        try {
            DecodedJWT decodedJWT = parseToken(request.getHeader(Constants.TOKEN_HEARD));
            return Long.parseLong(decodedJWT.getClaim(Constants.USER_TOKEN_KEY).asString());
        } catch (Exception e) {
            return null;
        }
    }

    public static Long getUserId(){
        return getUserId(ServletUtils.getRequest());
    }
}
